#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "log.hpp"

using namespace std;
enum{
    SocketFail = 1,
    BindFail,
    ListenFail,
    AcceptFail,
    ConnectFail
};
class Sock
{
public:
    Sock(uint16_t port, const string &ip = "0.0.0.0")
        : port_(port), ip_(ip)
    {
        local_.sin_family = AF_INET;
        local_.sin_port = htons(port_);
        local_.sin_addr.s_addr = inet_addr(ip_.c_str());
        len_ = sizeof(local_);
    }

    ~Sock()
    {
    }

    void Socket()
    {
        sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd_ < 0)
        {
            log(Fatal, "socket fail:%d %s", errno, strerror(errno));
            exit(SocketFail);
        }
    }

    void Bind()
    {

        int n = bind(sockfd_, (struct sockaddr *)&local_, len_);
        if (n < 0)
        {
            log(Fatal, "bind fail:%d %s", errno, strerror(errno));
            exit(BindFail);
        }
    }

    void Listen()
    {
        int n = listen(sockfd_, 10);
        if (n < 0)
        {
            log(Fatal, "listen fail:%d %s", errno, strerror(errno));
            exit(ListenFail);
        }
    }

    void Accept()
    {
        lis_sockfd_ = accept(sockfd_, (struct sockaddr*)&local_, &len_);//结构体会被覆盖为client的结构体
        if(lis_sockfd_ < 0)
        {
            log(Fatal, "accept fail:%d %s", errno, strerror(errno));
            exit(AcceptFail);
        }
    }

    void Connect()
    {
        int n = connect(sockfd_, (struct sockaddr*)&local_, len_);
        if(n < 0)
        {
            log(Warning, "connect fail:%d %s", errno, strerror(errno));
            exit(ConnectFail);
        }
    }

    int sockfd_;
    uint16_t port_;
    string ip_;

    int lis_sockfd_;
    struct sockaddr_in local_;
    socklen_t len_;
};